package gbench.appdemo.myworld.market.license;

import gbench.appdemo.myworld.market.SimpleMarket;
import gbench.appdemo.myworld.market.SimpleMarket.DRCR;
import gbench.appdemo.myworld.market.commodity.Commodity;
import gbench.appdemo.myworld.market.store.OnlineStore;

/**
 * 
 * @author gbench
 *
 * @param <T> CommodityLicense 的产品类型
 * @param <UE> CommodityLicense 所在的市场的一般等价物类型
 */
public  class CommodityLicense<T extends Commodity,UE extends Commodity> implements ICommodityLicense<T> {
    
    /**
     * 生成一个商品交易证书
     * @param storeId 交易者Id
     */
    public CommodityLicense(final String storeId) {
        this.storeId = storeId;
    }
    
    /**
     * 生成一个商品交易证书
     * @param storeId 交易者Id
     * @param commodity 商品对象
     */
    public CommodityLicense(final String storeId, final T commodity) {
        this.storeId = storeId;
        this.commodity = commodity;
    }
    
    public boolean equals(final CommodityLicense<T,UE> license) {
        return this.getCode().equals(license.getCode());
    }
    
    public int hashCode() {
        return this.getCode().hashCode();
    }
    
    public OnlineStore getOwner() {
        return this.getStoreById(this.storeId);
    }
    
    public String toString() {
        return this.getCode();
    }
    
    @SuppressWarnings("unchecked")
    public void setMarket(SimpleMarket< ? extends Commodity > market) {
        this.market = (SimpleMarket<UE>) market;
    }
    
    /**
     * 使用 (ta,na) - > 换取得 (ub,nb)
     * @param <U> 还如的对象类型
     * @param partB  (ub,nb) 来源 换取方式
     * @param ub 换入的对象
     * @param nb 还如的数量
     * @param ta 换出的对象
     * @param na 换出的数量
     */
    public <U extends Commodity> void commitTransaction(final DRCR drcr, 
        final T ta, final Number na, final ICommodityLicense<U> partB,final U ub, final Number nb) {
        
       final var final_ta = ta==null?this.getCommodity():ta;
       final var final_ub  = ub==null?partB.getCommodity():ub;
       
       // 设置交易
       this.market.withTransaction(drcr,final_ta,na,final_ub,nb,trade->{
           trade.setPartA(this);
           trade.setPartB(partB);
      });// withTransaction
    }
    
    /**
     * 使用 (ta,na) - > 换取得 (ub,nb)
     * @param <U> 还如的对象类型
     * @param partB  (ub,nb) 来源 换取方式
     * @param ub 换入的对象
     * @param nb 还如的数量
     * @param ta 换出的对象
     * @param na 换出的数量
     */
    public <U extends Commodity> void debitB(final ICommodityLicense<U> partB,
        final U ub, final Number nb, final T ta, final Number na) {
       this.commitTransaction(DRCR.CR, ta, na, partB, ub, nb);
    }
    
    /**
     * 使用 (ta,na) - > 换取得 (ub,nb)
     * @param <U> 还如的对象类型
     * @param partB  (ub,nb) 来源 换取方式
     * @param ub 换入的对象
     * @param nb 还如的数量
     * @param ta 换出的对象
     * @param na 换出的数量
     */
    public <U extends Commodity> void debitA(final ICommodityLicense<U> partB,
        final T ta, final Number na,final U ub, final Number nb) {
       this.commitTransaction(DRCR.DR, ta, na, partB, ub, nb);
    }
    
    /**
     * 使用 (ta,na) - > 换取得 (ub,nb)
     * @param <U> 还如的对象类型
     * @param partB  (ub,nb) 来源 换取方式
     * @param ub 换入的对象
     * @param nb 还如的数量 <br>
     * @param ta 换出的对象 换入对象默认为 TradeRole的 primaryCommodity 
     * @param na 换出的数量
     */
    public <U extends Commodity> void debitA(final ICommodityLicense<U> partB, 
        final Number na, final U ub, final Number nb) {
      this.debitA(partB, null, na, null, nb);
    }

    /**
     * 使用 (ta,na) - > 换取得 (ub,nb)
     * @param <U> 还如的对象类型
     * @param partB  (ub,nb) 来源 换取方式
     * @param ub 换入的对象
     * @param nb 还如的数量 <br>
     * @param ta 换出的对象 换入对象默认为 TradeRole的 primaryCommodity 
     * @param na 换出的数量
     */
    public <U extends Commodity> void debitB(ICommodityLicense<U> partB,U ub,Number nb,Number na) {
      this.debitB(partB, ub, nb, null, na);
    }
    
    /**
     * 使用 (ta,na) - > 换取得 (ub,nb)
     * @param <U> 还如的对象类型
     * @param partB  (ub,nb) 来源 换取方式
     * @param ub 换入的对象
     * @param nb 还如的数量 <br>
     * @param ta 换出的对象 换入对象默认为 TradeRole的 primaryCommodity 
     * @param na 换出的数量
     */
    public <U extends Commodity> void work(ICommodityLicense<U> partB,Number nb,Number na) {
       this.debitB(partB, null,nb,null,na);
    }
    
    /**
     * 使用 (ta,na) - > 换取得 (ub,nb)
     * @param <U> 还如的对象类型
     * @param partB  (ub,nb) 来源 换取方式
     * @param ub 换入的对象
     * @param nb 还如的数量 <br>
     * @param ta 换出的对象 换入对象默认为 TradeRole的 primaryCommodity 
     * @param na 换出的数量
     */
    public <U extends Commodity> void purchase(ICommodityLicense<U> partB,U ub,Number nb,T ta,Number na) {
      this.debitB(partB, ub, nb, ta, na);
    }
    
    /**
     * 使用 (ta,na) - > 换取得 (ub,nb)
     * @param <U> 还如的对象类型
     * @param partB  (ub,nb) 来源 换取方式
     * @param ub 换入的对象
     * @param nb 还如的数量 <br>
     * @param ta 换出的对象 换入对象默认为 TradeRole的 primaryCommodity 
     * @param na 换出的数量
     */
    @SuppressWarnings("unchecked")
    public <U extends Commodity> void purchase2(ICommodityLicense<U> partB,U ub,Number nb,Number na) {
        final var ta = (T)this.market.getUniversalEquivalent();
      this.debitB(partB, ub, nb, ta, na);
    }
    
    /**
     * 使用 (ta,na) - > 换取得 (ub,nb)
     * @param <U> 还如的对象类型
     * @param partB  (ub,nb) 来源 换取方式
     * @param ub 换入的对象
     * @param nb 还如的数量 <br>
     * @param ta 换出的对象 换入对象默认为 TradeRole的 primaryCommodity 
     * @param na 换出的数量
     */
    public <U extends Commodity> void purchase(ICommodityLicense<U> partB,U commodity,Number na,Number nb) {
       this.debitB(partB, null, nb, null, na);
    }
    
    /**
     * 使用 (ta,na) - > 换取得 (ub,nb)
     * @param <U> 还如的对象类型
     * @param partB  (ub,nb) 来源 换取方式
     * @param ub 换入的对象
     * @param nb 还如的数量 <br>
     * @param ta 换出的对象 换入对象默认为 TradeRole的 primaryCommodity 
     * @param na 换出的数量
     */
    public <U extends Commodity> void purchase(ICommodityLicense<U> partB,Number nb,Number na) {
        this.debitB(partB, null, nb, null,na);
    }
    
    /**
     * 使用 (ta,na) - > 换取得 (ub,nb)
     * @param <U> 还如的对象类型
     * @param partB  (ub,nb) 来源 换取方式
     * ub 换入的对象 默认为 partB 的 primaryCommodity
     * nb 还如的数量  默认为1
     * @param ta 换出的对象 换入对象默认为 TradeRole的 primaryCommodity 
     * @param na 换出的ta数量
     */
    public <U extends Commodity> void purchase(ICommodityLicense<U> partB,Number na) {
        this.debitB(partB, null, 1, na);
    }
    
    /**
     * 使用 (ta,na) - > 换取得 (ub,nb)
     * @param <U> 还如的对象类型
     * @param partB  (ub,nb) 来源 换取方式
     * @param ub 换入的对象
     * @param nb 还如的数量 <br>
     * @param ta 换出的对象 换入对象默认为 TradeRole的 primaryCommodity 
     * @param na 换出的数量
     */
    public <U extends Commodity> void purchase(ICommodityLicense<U> partB,U ub,Number na) {
        this.purchase(partB,ub,1,null,na);;
    }
    
    @Override
    public T getCommodity() {
        return commodity;
    }
    
    public SimpleMarket<UE> getMarket() {
        return market;
    }
    
    /**
     * 代码
     */
    public String getCode() {
        return this.storeId;
    }
    
    /**
     * 
     * @param id
     * @return
     */
    public OnlineStore getStoreById(String id) {
        if(store==null) {
            store=new OnlineStore(id);
        }
        return store;
    }
    
    protected String storeId;// 交易对象
    protected SimpleMarket<UE> market; // 所在市场
    protected T commodity;// 代理对象
    private OnlineStore store;

}